package com.dyava.commons.lang;

import net.sf.cglib.beans.BeanCopier;
import net.sf.cglib.beans.BeanMap;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class BeanUtils {
    static final Map<String, BeanCopier> BEAN_COPIERS = new ConcurrentHashMap<>();

    /**
	 * 拷贝bean<br>
     * 如果使用了ignoreProperties，则用spring拷贝<br>
     * 如果复制的对象是同一个类，则用cglib<br>
     * 最后再用Orika
	 * @param src
	 * @param target
	 * @param ignoreProperties
	 */
	public static<T>  void copy(T src,T target,String... ignoreProperties){
        if(src==null){
            throw new IllegalArgumentException("源对象不能为空");
        }
        if(target==null){
            throw new IllegalArgumentException("目标类型不能为空");
        }

        if(ignoreProperties.length>0){
            HashMap<String,Object> tmp = new HashMap<>();
            beanToMap(src,tmp);
            for(String k : ignoreProperties){
                tmp.remove(k);
            }
            mapToBean(tmp,target);

		}else{
            String key = src.getClass().getName();
            BeanCopier copier = BEAN_COPIERS.get(key);
            if (!BEAN_COPIERS.containsKey(key)) {
                copier = BeanCopier.create(src.getClass(), src.getClass(), false);
                BEAN_COPIERS.put(key, copier);
            }
            copier.copy(src, target, null);
		}
	}

    /**
     * 复制bean
     * @param src
     * @param targetClass
     * @param ignoreProperties
     * @param <T>
     * @return
     */
	public static<T> T clone(Object src,Class<T> targetClass,String... ignoreProperties){
        if(src==null){
            throw new IllegalArgumentException("源对象不能为空");
        }
        if(targetClass==null){
            throw new IllegalArgumentException("目标类型不能为空");
        }
		T target = null;
		try {
			target = (T)targetClass.getConstructor().newInstance();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		copy(src,target,ignoreProperties);
		return target;
	}
	
	/**
	 * 将对象拷贝给map
     * @param bean
     * @param map
	 * @return
	 */
    public static<T> void beanToMap(T bean,Map<String, Object> map) {
        if(bean==null){
            throw new IllegalArgumentException("源对象不能为空");
        }
        if(map==null){
            throw new IllegalArgumentException("目标类型不能为空");
        }
        BeanMap beanMap = BeanMap.create(bean);
        for (Object key : beanMap.keySet()) {
            map.put(key.toString(), beanMap.get(key));
        }
    }
    /**
     * 将对象复制为map
     * @param bean
     * @return
     */
    public static<T> Map<String, Object> beanToMap(T bean) {
        if(bean==null){
            throw new IllegalArgumentException("源对象不能为空");
        }
        Map<String, Object> map = new HashMap<String, Object>();
        beanToMap(bean,map);
        return map;
    }

	/**
	 * 将map拷贝给bean对象
	 * @param map
	 * @param bean
	 * @return
	 */
    public static<T> void mapToBean(Map<String, Object> map, T bean) {
        if(bean==null){
            throw new IllegalArgumentException("bean不能为空");
        }
        if(map==null){
            throw new IllegalArgumentException("map不能为空");
        }
        BeanMap beanMap = BeanMap.create(bean);
        beanMap.putAll(map);
    }
    /**
     * 将map复制为bean对象
     * @param map
     * @param beanClass
     * @return
     */
    public static<T> T mapToBean(Map<String, Object> map, Class<T> beanClass) {
        if(map==null){
            throw new IllegalArgumentException("map不能为空");
        }
        if(beanClass==null){
            throw new IllegalArgumentException("beanClass不能为空");
        }
        T target = null;
        try {
            target = (T)beanClass.getConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        mapToBean(map,target);
        return target;
    }

}
